package http;

import android.os.AsyncTask;
import android.webkit.URLUtil;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.FormBodyPart;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

import java.io.File;
import java.io.IOException;

/**
 * 上传大文件
 */
public class HttpMultipartPost extends AsyncTask<HttpResponse, Integer, String> {

    private final static String TAG = HttpMultipartPost.class.getSimpleName();
    private final static String BOUNDARY = "---------------------------7da2137580612";

    //上传地址
    private String url;
    //总共的文件大小
    private long totalSize;
    //文件列表的form-data名称
    private String filePartName;
    //文件列表
    private String[] files;
    //参数
    private FormBodyPart[] parts;
    //上传过程中的回调
    private CallBack call;
    //上传结束后的回调
    private CallBackMsg callMsg;
    //编码
    private String encode = HTTP.UTF_8;

    /**
     * 定义上传过程中的回调接口
     */
    public interface CallBack {
        public void update(Integer i);
    }

    /**
     * 定义上传结束后的回调接口
     */
    public interface CallBackMsg {
        public void msg(String msg);
    }

    /**
     * 设置上传过程中的回调
     * @param call
     */
    public void setCallBack(CallBack call) {
        this.call = call;
    }

    /**
     * 设置上传结束后的回调
     * @param callMsg
     */
    public void setCallBackMsg(CallBackMsg callMsg) {
        this.callMsg = callMsg;
    }

    /**
     * 构造函数
     * @param url
     * @param fileEncode
     * @param filePartName
     * @param files
     * @param parts
     */
    public HttpMultipartPost(String url, String fileEncode, String filePartName, String[] files, FormBodyPart... parts) {
        super();

        this.url = url;
        this.filePartName = filePartName;
        this.files = files;
        this.parts = parts;
        this.encode = fileEncode.equals("") ? HTTP.UTF_8 : fileEncode;
    }

    /**
     * 请求前的校验工作
     */
    @Override
    protected void onPreExecute() {
        if (!URLUtil.isNetworkUrl(url)) {
            throw new IllegalArgumentException("unvalid url for post");
        }
    }

    /**
     * 发送请求
     * @param responses
     * @return
     */
    @Override
    protected String doInBackground(HttpResponse... responses) {
        HttpClient client = new DefaultHttpClient();
        HttpContext context = new BasicHttpContext();
        HttpPost post = new HttpPost(url);

        try {

            NDMultiPartEntity content = new NDMultiPartEntity(HttpMultipartMode.BROWSER_COMPATIBLE,
                    new NDMultiPartEntity.ProgressListener() {
                        @Override
                        public void transferred(long num) {
                            publishProgress((int) ((num / (float) totalSize) * 100));
                        }
                    }
            );

            for (String file : files) {
                content.addPart(filePartName, new FileBody(new File(file)));
            }

            for (FormBodyPart part : parts) {
                content.addPart(part);
            }

            totalSize = content.getContentLength();
            post.setEntity(content);
            HttpResponse res = client.execute(post, context);
            String resStr = EntityUtils.toString(res.getEntity());
            return resStr;
        } catch (IOException e) {
            e.printStackTrace();
            return "{\"msg\":\"post failed!\"}";
        }
    }

    @Override
    protected void onProgressUpdate(Integer... progress) {
        if (call != null)
            call.update(progress[0]);
    }

    @Override
    protected void onPostExecute(String s) {
        if (callMsg != null)
            callMsg.msg(s);
    }

}
